# -*- coding:utf-8 -*-

"""
用户管理

IndexHandler
RootAddHandler
UserAddHandler
SigninHandler
LoginHandler

"""

from tornado.web       import RequestHandler

from utils.routes      import route
from utils.encrypt     import encrypt_password, validate_password
from utils             import mongo
from utils.tokens      import token_en
from utils.errors      import err_param

from configure         import config
from configure.config  import DB_NAME, COLL_USER

from asyncmongo.errors import IntegrityError

from service.base      import AuthHandler, BaseWebHandlerV2

from loog.mylog         import flogger as logger

import tornado
import datetime, json


@route(r'/', name='index')
class IndexHandler(BaseWebHandlerV2):
    """ 渲染前端用的首页 """

    def get(self):
        self.render('index.html')


@route(r'/root/add', name='root_add')
class RootAddHandler(BaseWebHandlerV2):
    """ 添加超级管理员

    role_name: root
    role_id  : 1
    authcode : 55c808909tigered22388bbb
    """

    @tornado.web.asynchronous
    @tornado.gen.engine
    def get(self):

        try:
            username = self.get_argument('username', '')
            password = self.get_argument('password', '')
            authcode = self.get_argument('authcode', '')

            if len(username) < 6 or len(password) < 6: raise ValueError
            if authcode != config.AUTHCODE: raise ValueError
        except Exception, e:
            logger.exception(e)
            self.write(err_param)
            self.finish()
            return

        hashed = encrypt_password(password, config.AUTHCODE)

        user_dict = {
            'username':username,
            'password':hashed,
            'roleid'  :1,
            'rolename':'root'
        }

        try:
            yield tornado.gen.Task(mongo.insert, DB_NAME, COLL_USER, user_dict)
        except Exception, e:
            logger.exception(e)
            self.write({'code':500})
            self.finish()
            return

        logger.info('- ROOT_ADDED: %s' % username)
        self.write({
            'code':200,
            'username':username
        })
        self.finish()


@route(r'/user/add', name='user_add')
class UserAddHandler(AuthHandler):
    """ 管理员添加普通账户

    1. 只有管理员有权限添加账户
    2. 普通账户用于业务操作

    TODO:
        1. 目前并没有 角色/权限 相关需求，所以权限判断就写死在这了
    """

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):

        try:
            token    = self.request.headers.get('TData',{})
            udict    = json.loads(self.request.body)
            username = udict['username']
            password = udict.get('password', 'idealsee')

            if len(username) < 6 or len(password) < 6: raise ValueError
        except Exception, e:
            logger.exception(e)
            self.write(err_param)
            self.finish()
            return

        if token.get('r',0) != 1:
            self.write({'code':401})
            self.finish()
            return

        hashed = encrypt_password(password, config.AUTHCODE)

        user_dict = {
            'username':username,
            'password':hashed,
            'roleid'  :2,
            'rolename':'manager'
        }

        try:
            yield tornado.gen.Task(mongo.insert, DB_NAME, COLL_USER, user_dict)
        except IntegrityError, e:
            logger.exception(e)
            self.write({'code':10001})
            self.finish()
            return
        except Exception, e:
            logger.exception(e)
            self.write({'code':500})
            self.finish()
            return

        logger.info('- USER_ADDED: %s' % username)

        self.write({
            'code':200,
            'data':{
                'username':username
            }
        })
        self.finish()


@route(r'/user/list', name='user_list')
class UserListHandler(AuthHandler):
    """ 用户列表

    只有管理员有权限查看
    """

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):

        token = self.request.headers.get('TData',{})

        if token.get('r', 0) != 1:
            self.write({'code':401})
            self.finish()
            return

        query  = {'roleid':2}
        #query = {'username': {'$regex':'.*%s.*'%'ter'}}
        fields = {'username':1}
        try:
            users = yield tornado.gen.Task(
                                        mongo.find_all,
                                        DB_NAME,
                                        COLL_USER,
                                        query,
                                        fields)
        except Exception, e:
            logger.exception(e)
            self.write({'code':500})
            self.finish()
            return

        self.write({'code':200,'data':users})
        self.finish()


@route(r'/user/signin', name='user_signin')
class SigninHandler(BaseWebHandlerV2):
    """ 用户登录 """

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):

        try:
            udict    = json.loads(self.request.body)
            username = udict['username']
            password = udict['password']
            seconds  = udict.get('seconds', 0)

            if len(username) < 6 or len(password) < 6: raise ValueError
        except Exception, e:
            logger.exception(e)
            self.write(err_param)
            self.finish()
            return

        query = {'username':username}
        try:
            user = yield tornado.gen.Task(mongo.find_one,DB_NAME,COLL_USER,query)
        except Exception, e:
            self.write({'code':500})
            self.finish()
            return

        if not user:
            logger.info('- 404_USER: %s/%s' % (username,password))
            self.write({'code':404})
            self.finish()
            return

        if not validate_password(user['password'],password,config.AUTHCODE):
            logger.info('- WRONG_PASSWD: %s/%s' % (username,password))
            self.write({'code':404})
            self.finish()
            return

        # TODO 存一份token或者标识到数据库或者redis，用于表示用户的登录状态

        # 生成 token
        seconds = int(seconds) if seconds else config.JWT_EXP
        payload = {
            '_id' :user['_id'],
            'n'   :username,
            'r'   :user['roleid'],
            'exp' :datetime.datetime.utcnow() + \
                   datetime.timedelta(seconds=seconds)   # expired_in
        }
        token = token_en(payload, config.JWT_SECRET, config.JWT_ALGORITHM)
        logger.info('- SIGNED: %s/%s' % (username, password))

        res = {
            'code':200,
            'data':{
                'username':username,
                'token'   :token
            }
        }
        self.write(res)
        self.finish()


@route(r'/user/passwd', name='user_passwd')
class SigninHandler(AuthHandler):
    """ 用户 - 修改密码 """

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self):

        try:
            token      = self.request.headers.get('TData',{})
            udict      = json.loads(self.request.body)
            passwd     = udict['passwd']
            passwd_new = udict['passwd_new']
            passwd2    = udict['passwd_new2']
        except Exception, e:
            logger.exception(e)
            self.write(err_param)
            self.finish()
            return

        query = {'username':token['n']}
        try:
            user = yield tornado.gen.Task(mongo.find_one,DB_NAME,COLL_USER,query)
        except Exception, e:
            self.write({'code':500})
            self.finish()
            return

        if not user:
            logger.info('- 404_USER: %s/%s' % (token['n'], passwd))
            self.write({'code':404})
            self.finish()
            return

        if not validate_password(user['password'],passwd,config.AUTHCODE):
            logger.info('- WRONG_PASSWD: %s/%s' % (token['n'],passwd))
            self.write({'code':404})
            self.finish()
            return

        # 兼容用, 判断密码是否正确也用的这个接口
        if len(passwd_new) == 0 or len(passwd2) == 0 or passwd_new!=passwd2:
            self.write({'code':406})
            self.finish()
            return

        # 新密码
        hashed  = encrypt_password(passwd_new, config.AUTHCODE)

        query   = {'username':token['n']}
        updates = {'password':hashed}
        try:
            user = yield tornado.gen.Task(
                    mongo.update,
                    DB_NAME,
                    COLL_USER,
                    query,
                    updates)
        except Exception, e:
            self.write({'code':500})
            self.finish()
            return

        logger.info('- 200_modified_password: %s' % passwd)
        res = {'code':200}
        self.write(res)
        self.finish()


# V1.0 接口
@route('/login/?', 'login')
class LoginHandler(RequestHandler):
    """ 登陆之后，才能做其它操作 """

    def get(self):
        """ 渲染登录页面 """

        self.render('login.html')

    @tornado.web.asynchronous
    @tornado.gen.engine
    def post(self, *argl, **argd):
        username = self.get_argument('username', None)
        password = self.get_argument('password', None)

        if username != config.ADMIN_USER or password != config.ADMIN_PASS:
            self.finish({'code': 1, 'info': 'username or password error!'})
            return

        self.clear_all_cookies()
        self.set_secure_cookie(config.COOKIE_KEY, config.COOKIE_VALUE, expires_days=1)
        self.finish({'code': 0, 'info': 'login success!', 'redirect_url': '/manage'})



